package org.example.java.util.concurrency.data_structure;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * User: ZhangJuntao
 * Date: 13-11-17
 * Time: 下午12:41
 */
public class CopyOnWriteArrayListTest {
  final static List<Integer> cowList = new CopyOnWriteArrayList<Integer>();
  //虽然在列表上add(),remove()和get()方法现在对线程是安全的，但遍历时仍然会抛出ConcurrentModificationException！
  final static List<Integer> list = Collections.synchronizedList(new ArrayList<Integer>());
  final static ArrayList<Integer> arrayList = new ArrayList<Integer>();

  public static void main(String... args) throws InterruptedException {
    testCopyOnWriteArrayList();
//    testSynchronizedArrayList();
//    testErrorArrayList();

  }

  //ConcurrentModificationException
  private static void testErrorArrayList() {
    for (int i = 0; i < 10; i++) {
      synchronized (arrayList) {
        arrayList.add(i);
      }
    }

    new Thread() {
      @Override
      public void run() {
        Iterator<Integer> it = arrayList.iterator();
        while (it.hasNext()) {
          try {
            sleep(1);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          System.out.println(it.next());
        }
      }
    }.start();

    new Thread() {
      @Override
      public void run() {
        try {
          sleep(5);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        arrayList.clear();
        System.out.println("==clear==");
      }
    }.start();
  }

  private static void testSynchronizedArrayList() {
    for (int i = 0; i < 10; i++) {
      list.add(i);
    }

    new Thread() {
      @Override
      public void run() {
//        synchronized (list) {
//          Iterator<Integer> it = list.iterator();
//          while (it.hasNext()) {
//            System.out.println(it.next());
//            try {
//              sleep(1);
//            } catch (InterruptedException e) {
//              e.printStackTrace();
//            }
//          }
//        }

        // update
        Iterator<Integer> it = list.iterator();
        while (it.hasNext()) {
          System.out.println(it.next());
          try {
            sleep(100);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }.start();

    new Thread() {
      @Override
      public void run() {
//        try {
//          sleep(5);
//        } catch (InterruptedException e) {
//          e.printStackTrace();
//        }
//        synchronized (list) {
//          list.clear();
//        }
//        System.out.println("==clear==");

        for (int i = 0; i < 10; i++) {
          list.set(i, i + 10);
          try {
            sleep(100);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      }
    }.start();
  }

  private static void testCopyOnWriteArrayList() {
    for (int i = 0; i < 10; i++) {
      cowList.add(i);
    }

    new Thread() {
      @Override
      public void run() {

        //可能会报下标out of array.
        try {
          sleep(200);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
        for (Integer integer : cowList) {
          System.out.println(integer);
          try {
            sleep(100);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }

//        Iterator<Integer> it = cowList.iterator();
//        while (it.hasNext()) {
//          try {
//            sleep(1);
//          } catch (InterruptedException e) {
//            e.printStackTrace();
//          }
//          System.out.println(it.next());
//        }
      }
    }.start();

    new Thread() {
      @Override
      public void run() {

        for (int i = 0; i < 10; i++) {
          cowList.set(i, i + 10);
          try {
            sleep(100);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }

//        try {
//          sleep(4);
//        } catch (InterruptedException e) {
//          e.printStackTrace();
//        }
//        cowList.clear();
//        System.out.println("==clear==");
      }
    }.start();
  }
}
